package ch.il07.converter.persistance.tests;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.List;

import org.junit.Before;
import org.junit.Test;

import ch.il07.converter.persistence.Persistence;
import ch.il07.converter.persistence.PersistenceHelper;
import ch.il07.converter.persistence.entities.AccessLevel;
import ch.il07.converter.persistence.entities.Measurand;
import ch.il07.converter.persistence.entities.Unit;
import ch.il07.converter.persistence.exceptions.AlreadyDefinedException;
import ch.il07.converter.persistence.exceptions.NoSuchMeasurandException;
import ch.il07.converter.persistence.exceptions.NoSuchUnitException;
import ch.il07.converter.persistence.exceptions.PersistenceException;
import ch.il07.utils.RandomHelper;

/**
 * 
 * @desc username is always also used as the password
 * 
 */
public class DeleteUnit {

	private Persistence persistence;

	@Before
	public void setUp() {
		try {
			persistence = PersistenceHelper.getPersistence();
		} catch (PersistenceException e) {
			fail(e.getMessage());
		}
	}

	@Test
	public void deleteUnit() {
		Unit u = new Unit(RandomHelper.randString(), 1D);
		Measurand m = new Measurand(RandomHelper.randString(), u);

		try {
			persistence.addMeasurand(m, null);
		} catch (AlreadyDefinedException e) {
			fail(e.getMessage());
		} catch (PersistenceException e) {
			fail(e.getMessage());
		}

		{ // delete it
			try {
				persistence.deleteUnit(m, u);
			} catch (NoSuchUnitException e) {
				fail(e.getMessage());
			} catch (NoSuchMeasurandException e) {
				fail(e.getMessage());
			} catch (PersistenceException e) {
				fail(e.getMessage());
			}

		}
	}

	@Test
	public void unexistentUnit() {
		Measurand m = new Measurand(RandomHelper.randString(), new Unit(RandomHelper.randString(), 1D, 0D));

		{ // insert measurand
			try {
				persistence.addMeasurand(m, null);

				List<Measurand> measurands = persistence.getMeasurands();

				boolean measurandIsAvailable = false;
				for (Measurand measurand : measurands) {
					if (measurand.getName().equals(m.getName())) {
						m = measurand;
						measurandIsAvailable = true;
						break;
					}
				}
				assertTrue("measurand '" + m.getName() + "' should exist in db",
						measurandIsAvailable);
			} catch (AlreadyDefinedException e) {
				fail(e.getMessage());
			} catch (PersistenceException e) {
				fail(e.getMessage());
			}
		}

		{ // delete an !!UNEXISTENT!! unit
			try {
				persistence.deleteUnit(m, new Unit(RandomHelper.randString(), 13D, 22D));
				fail("Should throw an NoSuchUnitException");
			} catch (NoSuchUnitException e) {
				// expected
			} catch (NoSuchMeasurandException e) {
				fail(e.getMessage());
			} catch (PersistenceException e) {
				fail(e.getMessage());
			}
		}
	}

	/**
	 * @desc try to delete an existant unit with an unexistent/wrong measurand
	 */
	@Test
	public void unexistentMeasurandString() {
		Measurand invalidMeasurand = new Measurand(RandomHelper.randString(), new Unit(RandomHelper.randString(),
				2.2, 6.5));
		Unit validUnit = new Unit(RandomHelper.randString(), 1D, 0D);
		Measurand validMeasurand = new Measurand(RandomHelper.randString(), validUnit);

		String username = RandomHelper.randString();

		{ // insert the valid one

			try {
				persistence.addUser(username, RandomHelper.getEmail(username), username,
						AccessLevel.USER);
				assertNotNull("User '" + username
						+ "' should exist in database", persistence.getUser(username,
						username));

				persistence.addMeasurand(validMeasurand, username);
				List<Measurand> measurands = persistence.getMeasurands(username);

				boolean measurandIsAvailable = false;
				for (Measurand measurand : measurands) {
					if (measurand.getName().equals(validMeasurand.getName())) {
						measurandIsAvailable = true;
						break;
					}
				}
				assertTrue("measurand '" + validMeasurand.getName() + "' should exist in db",
						measurandIsAvailable);
			} catch (AlreadyDefinedException e) {
				fail(e.getMessage());
			} catch (PersistenceException e) {
				fail(e.getMessage());
			}
		}
		
		{ // try to delete
			try {
				persistence.deleteUnit(invalidMeasurand, validUnit);
				fail("Should throw a NoSuchMeasurandException");
			} catch (IllegalArgumentException e) {
				// expected
			} catch (PersistenceException e) {
				fail(e.getMessage());
			}
		}
	}
}
